package com.ruoyi.system.service.impl;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.ruoyi.common.utils.DateUtils;
import org.apache.shiro.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.VideoDataMapper;
import com.ruoyi.system.domain.VideoData;
import com.ruoyi.system.service.ITaskDataRelService;
import com.ruoyi.system.service.IVideoDataService;
import com.ruoyi.common.core.text.Convert;

/**
 * 数据管理Service业务层处理
 * 
 * @author wsx
 * @date 2025-07-30
 */
@Service
public class VideoDataServiceImpl implements IVideoDataService {
    @Autowired
    private VideoDataMapper videoDataMapper;

    @Autowired
    private ITaskDataRelService taskDataRelService;

    /**
     * 查询数据管理
     * 
     * @param dataId 数据管理主键
     * @return 数据管理
     */
    @Override
    public VideoData selectVideoDataByDataId(Long dataId) {
        return videoDataMapper.selectVideoDataByDataId(dataId);
    }

    /**
     * 查询数据管理列表
     * 
     * @param videoData 数据管理
     * @return 数据管理
     */
    @Override
    public List<VideoData> selectVideoDataList(VideoData videoData) {
        videoData.setDelFlag("0");
        List<VideoData> selectVideoDataList = videoDataMapper.selectVideoDataList(videoData);
        for (VideoData videoData2 : selectVideoDataList) {
            videoData2.setTaskId(taskDataRelService.selectTaskIdByDataId(videoData2.getDataId()));
        }
        return selectVideoDataList;
    }

    /**
     * 根据ID查询数据管理列表
     * 
     * @param ids 数据管理主键
     * @return 数据管理集合
     */
    @Override
    public List<VideoData> selectVideoDataListByIds(String ids, VideoData videoData) {
        videoData.setDelFlag("0");
        videoData.setIds(ids);
        return videoDataMapper.selectVideoDataListByIds(videoData);
    }

    /**
     * 新增数据管理
     * 
     * @param videoData 数据管理
     * @return 结果
     */
    @Override
    public int insertVideoData(VideoData videoData) {
        videoData.setCreateTime(DateUtils.getNowDate());
        videoData.setIsArchived("0");
        return videoDataMapper.insertVideoData(videoData);
    }

    /**
     * 修改数据管理
     * 
     * @param videoData 数据管理
     * @return 结果
     */
    @Override
    public int updateVideoData(VideoData videoData) {
        videoData.setUpdateTime(DateUtils.getNowDate());
        videoData.setCollectDuration(
                DateUtils.getDuration(videoData.getEndCollectTime(), videoData.getStartCollectTime()));
        return videoDataMapper.updateVideoData(videoData);
    }

    /**
     * 批量删除数据管理
     * 
     * @param dataIds 需要删除的数据管理主键
     * @return 结果
     */
    @Override
    public int deleteVideoDataByDataIds(String dataIds) {
        return videoDataMapper.deleteVideoDataByDataIds(Convert.toStrArray(dataIds));
    }


    @Value("${ffmpeg.savePath}")
    private String localVideoDir;

    /**
     * 逻辑删除数据管理
     * 
     * @param dataIds 需要删除的数据管理主键
     * @return 结果
     */
    @Override
    public int updateDelFlag(String dataIds) {
        String[] strArray = Convert.toStrArray(dataIds);
        for (String str : strArray) {
            Long dataId = Long.parseLong(str);

            // 查询视频数据（校验存在性）
            VideoData videoData = videoDataMapper.selectVideoDataByDataId(dataId);
            if (videoData == null) {
                System.err.println("视频数据不存在，dataId:"+ dataId);
                continue;
            }

            // 路径处理：统一格式
            String storagePath = videoData.getStoragePath();
            String telemetryPath = videoData.getTelemetryStoragePath();

            System.err.println("/storagePath-------" + storagePath);

            List<String> deleteFailFiles = new ArrayList<>();

            // 处理视频存储路径
            if (StringUtils.hasText(storagePath)) {
                // 统一分隔符为系统原生
                String normalizedStoragePath = storagePath.replace("\\", File.separator)
                        .replace("/", File.separator);
                // 去除开头多余的分隔符
                if (normalizedStoragePath.startsWith(File.separator)) {
                    normalizedStoragePath = normalizedStoragePath.substring(1);
                }

                // 构建绝对路径
                Path baseDirPath = Paths.get(localVideoDir);
                Path absoluteStoragePathObj = baseDirPath.resolve(normalizedStoragePath);
                String absoluteStoragePath = absoluteStoragePathObj.toString();

                System.err.println("absoluteStoragePath（视频绝对路径）--------" + absoluteStoragePath);

                // 删除视频目录
                deleteDirWithForceRelease(new File(absoluteStoragePath), deleteFailFiles);
            }

            // 处理遥测存储路径（增加null检查）
            if (StringUtils.hasText(telemetryPath)) {
                // 统一telemetryPath的分隔符
                String normalizedTelemetryPath = telemetryPath.replace("\\", File.separator)
                        .replace("/", File.separator);
                // 拼接遥测根目录
                String telemetryStoragePath = "telemetryStoragePath" + File.separator + normalizedTelemetryPath;
                // 去除路径中可能的重复分隔符
                telemetryStoragePath = telemetryStoragePath.replace(File.separator + File.separator, File.separator);

                System.err.println("telemetryStoragePath（相对路径）--------" + telemetryStoragePath);

                // 构建绝对路径
                Path baseDirPath = Paths.get(localVideoDir);
                Path absoluteTelemetryPathObj = baseDirPath.resolve(telemetryStoragePath);
                String absoluteTelemetryStoragePath = absoluteTelemetryPathObj.toString();

                System.err.println("absoluteTelemetryStoragePath（遥测绝对路径）--------" + absoluteTelemetryStoragePath);

                // 删除遥测目录
                deleteDirWithForceRelease(new File(absoluteTelemetryStoragePath), deleteFailFiles);
            } else {
                System.err.println("telemetryPath为空，跳过遥测文件删除");
            }

            // 删除数据库中的数据记录
            int deleteCount = videoDataMapper.deleteVideoDataByDataId(dataId);

            // 处理删除失败的文件
            if (!deleteFailFiles.isEmpty()) {
                System.err.println("删除文件失败列表："+ deleteFailFiles);
                // 可以根据业务需求决定是否继续执行或抛出异常
            }
        }
        return strArray.length;
    }


    /**
     * 核心删除方法：强制删除目录（含内容），JDK 8 兼容
     * @param target 目标文件/目录
     * @param failList 失败记录列表
     */
    private void deleteDirWithForceRelease(File target, List<String> failList) {
        if (target == null || !target.exists()) {
            failList.add("目标不存在：" + (target != null ? target.getAbsolutePath() : "null"));
            return;
        }

        // 处理文件：重试删除（应对占用）
        if (target.isFile()) {
            boolean deleted = forceDeleteFile(target);
            if (deleted) {
                System.err.println("文件删除成功：" + target.getAbsolutePath());
            } else {
                failList.add("文件删除失败（已重试3次）：" + target.getAbsolutePath());
            }
            return;
        }

        // 处理目录：先删子内容，再删目录
        File[] childFiles = target.listFiles();
        if (childFiles == null) {
            failList.add("无法读取目录子内容（权限不足）：" + target.getAbsolutePath());
            return;
        }
        // 递归删除所有子内容
        for (File child : childFiles) {
            deleteDirWithForceRelease(child, failList);
        }

        // 删除空目录（重试）
        boolean dirDeleted = forceDeleteDir(target);
        if (dirDeleted) {
            System.err.println("目录删除成功：" + target.getAbsolutePath());
        } else {
            failList.add("目录删除失败（已重试3次）：" + target.getAbsolutePath());
        }
    }

    /**
     * 强制删除空目录（重试机制）
     * @param dir 目标目录
     * @return 是否删除成功
     */
    private boolean forceDeleteDir(File dir) {
        // 先确认目录为空
        if (dir.listFiles() != null && dir.listFiles().length > 0) {
            return false;
        }
        // 重试3次
        for (int i = 0; i < 3; i++) {
            try {
                if (dir.delete()) {
                    return true;
                }
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
        return false;
    }

    /**
     * 强制删除文件（JDK 8 兼容，无 var 关键字）
     * @param file 目标文件
     * @return 是否删除成功
     */
    private boolean forceDeleteFile(File file) {
        // 重试3次，每次间隔1秒
        for (int i = 0; i < 3; i++) {
            try {
                // 释放文件资源（JDK 8 正确关闭流，无 var）
                releaseFileResource(file);
                // 执行删除
                if (file.delete()) {
                    return true;
                }
                // 等待1秒重试
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            } catch (Exception e) {
                continue; // 忽略临时异常
            }
        }
        return false;
    }

    /**
     * 释放文件资源（修复 Files.flush 错误，JDK 8 兼容）
     * @param file 目标文件
     */
    private void releaseFileResource(File file) {
        RandomAccessFile raf = null; // JDK 8 需显式声明类型，不能用 var
        try {
            // 打开文件后立即关闭，强制释放JVM持有的文件句柄
            raf = new RandomAccessFile(file, "r");
            raf.close(); // 显式关闭流
        } catch (IOException e) {
            // 忽略异常：说明文件未被JVM占用（可能是外部进程占用）
        } finally {
            // 确保流一定关闭（避免资源泄漏）
            if (raf != null) {
                try {
                    raf.close();
                } catch (IOException e) {
                    // 忽略关闭异常
                }
            }
        }
    }


    /**
     * 删除数据管理信息
     * 
     * @param dataId 数据管理主键
     * @return 结果
     */
    @Override
    public int deleteVideoDataByDataId(Long dataId) {
        return videoDataMapper.deleteVideoDataByDataId(dataId);
    }
}
